﻿var extScope;

/**
 * Retrieve nested item from object/array
 * @param {Object|Array} obj
 * @param {String} path dot separated
 * @param {*} def default value ( if result undefined )
 * @returns {*}
 */
function Path(obj, path, def) {
    var i, len;

    for (i = 0, path = path.split('.'), len = path.length; i < len; i++) {
        if (!obj || typeof obj !== 'object') return def;
        obj = obj[path[i]];
    }

    if (obj === undefined) return def;
    return obj;
}

/* Global settings variable for Formly settings... */
function GetConfig() {
    this.url = null, 
    this.method = "GET",
    this.params = {},
    this.headers = { 'Cache-Control': 'no-cache' }
};

function PostConfig() {
    this.url = null,
    this.method = "POST",
    this.data = {},
    this.headers = { 'Cache-Control': 'no-cache' }
};

function FormlySettings() {
    this.load = null,
    this.send = null,
    this.container = '',
    this.callbackSuccess = null,
    this.callbackError = null,
    this.shortcutCallback = null,
    this.onloadCallback = null,
    this.beforeSumbit = null;
};

FormlySettings.prototype.setLoad = function (urlCnfg) {
    this.load = urlCnfg;
};

FormlySettings.prototype.setSend = function (urlCnfg) {
    this.send = urlCnfg;
};

FormlySettings.prototype.createPostConfig = function (url, params) {
    var retValue = new PostConfig();

    retValue.url = url;
    retValue.data = params;

    return retValue;
};

FormlySettings.prototype.createGetConfig = function (url, params) {
    var retValue = new GetConfig();

    retValue.url = url;
    retValue.params = params;

    return retValue;
};

function FormlyManager(settings) {
//function FormlyManager(loadUrl, sendUrl, container, callbackSuccess, callbackError, shortcutCallback, onloadCallback) {

    'use strict';

    var loadUrl = settings.load;
    var sendUrl = settings.send;
    var container = settings.container;
    var callbackSuccess = settings.callbackSuccess;
    var callbackError = settings.callbackError;
    var shortcutCallback = settings.shortcutCallback;
    var onloadCallback = settings.onloadCallback;
    var beforeSumbit = settings.beforeSumbit;

    //
    var app = angular.module('formlyExample', ['formly', 'formlyBootstrap', 'FormlyNET'], function config(formlyConfigProvider, CustomTypesProvider) {
        formlyConfigProvider.extras.removeChromeAutoComplete = true;

        formlyConfigProvider.setType(CustomTypesProvider.getTypes(container));
    });

    app.controller('MainCtrl', function MainCtrl($http, $scope, $q, CustomTypes, FieldsService) {
        var vm = this;

        extScope = $scope;

        // funcation assignment
        vm.onSubmit = onSubmit;

        vm.model = {};

        vm.Load = function (loadUrl) {
            vm.loadingData = FieldsService.getFields(loadUrl).then(function (result) {

                if ($.isArray(result.data)) {
                    // Edit...
                    vm.fields = JSON.parse(result.data[0], function (key, value) {
                        return Reviver(key, value);
                    });
                    vm.model = JSON.parse(result.data[1]);
                } else {
                    // Insert...
                    vm.fields = JSON.parse(result.data, function (key, value) {
                        return Reviver(key, value);
                    });
                    vm.model = {};
                }

                /* check all fields to bind, eventually, the addOn button click event... */
                AddOnButtons(vm.fields);

                /* checks for uiSelect2 fileds to bind the refreshItems standard Callback... */
                BindCallback(vm.fields);

                vm.originalFields = angular.copy(vm.fields);

                if (onloadCallback != undefined) {
                    onloadCallback();
                }

            });
        }

        // Note, normally I prefer to use the router and resolve
        // async dependencies into my controller, but I think
        // this gives you the idea of what you're supposed to do...  api/formly/
        // if url is webform webmethod: 'TestFormly2.aspx/LoadData' -> POST -> JSON.parse(result.data.d)
        // if uel is Web APi controller: api/formly/LoadFields -> GET -> JSON.parse(result.data)
        vm.loadingData = FieldsService.getFields(loadUrl).then(function (result) {

            if ($.isArray(result.data)) {
                // Edit...
                vm.fields = JSON.parse(result.data[0], function (key, value) {
                    return Reviver(key, value);
                });
                vm.model = JSON.parse(result.data[1]);
            } else {
                // Insert...
                vm.fields = JSON.parse(result.data, function (key, value) {
                    return Reviver(key, value);
                });
                vm.model = {};
            }

            /* check all fields to bind, eventually, the addOn button click event... */
            AddOnButtons(vm.fields);

            /* checks for uiSelect2 fileds to bind the refreshItems standard Callback... */
            BindCallback(vm.fields);

            vm.originalFields = angular.copy(vm.fields);

            if (onloadCallback != undefined) {
                onloadCallback();
            }

        });

        $scope.SetGetUrl = function (url, container) {
            var settings = new FormlySettings();
            settings.container = container;
            settings.setLoad(settings.createGetConfig(url));

            return settings.load;
        }

        $scope.SetPostUrl = function (url, container) {
            var settings = new FormlySettings();
            settings.container = container;
            settings.setLoad(settings.createPostConfig(url));

            return settings.load;
        }

        $scope.ShowDatepicker = function () {
            datepicker.open($event)
        }

        function Reviver(key, value) {
            if (value && (typeof value === 'string') && value.indexOf("function") === 0) {
                // we can only pass a function as string in JSON ==> doing a real function
                var jsFunc = new Function('return ' + value)();
                return jsFunc;
            }

            return value;
        }

        function AddOnButtons(fields) {
            $.each(fields, function (index, item) {
                var objR = Path(item, 'templateOptions.addonRight');

                if (objR !== undefined) {
                    if (objR.onClick !== undefined) {
                        var fR = objR.onClick;
                        objR.onClick = function (options, scope) { item.type == 'asyncselect' ? '' : eval(fR)(options, scope); }
                    }
                }

                var objL = Path(item, 'templateOptions.addonLeft');
                if (objL !== undefined) {
                    if (objL.onClick !== undefined) {
                        var fL = objL.onClick;
                        objL.onClick = function (options, scope) { item.type == 'asyncselect' ? '' : eval(fR)(options, scope); }
                    }
                }
            });
        }

        function BindCallback(fields) {
            $.each(fields, function (index, item) {
                if (item.type == 'ui-select-single-search') {
                    item.templateOptions.refresh = refreshItems;
                }
            });
        }

        function refreshItems(name, field) {
            var promise;
            var temp = '';

            if (!name) {
                promise = $q.when({ results: [] });
            } else {
                var data = { name: name, field: field };
                var endpoint = field.templateOptions.callback;

                temp = field.templateOptions.label;
                field.templateOptions.label = temp + ' ...searching...';
                promise = $http.post(endpoint, data);
            }

            return promise.then(function (response) {
                field.templateOptions.options = response.data;
                field.templateOptions.label = temp;
            });
        }

        function onSubmit() {
            var data = JSON.stringify(vm.model);
            //alert(data, null, 2);

            if (beforeSumbit != undefined) {
                var retValue = beforeSumbit(data);

                if (!retValue) {
                    return;
                }
            }


            if ((sendUrl == '') || (sendUrl == undefined)) {

                if (shortcutCallback != undefined) {
                    shortcutCallback(data);
                }

            } else {
                sendUrl.data = data;
                //$http.post(sendUrl).then(function successCallback(response) {
                $http(sendUrl).then(function successCallback(response) {
                    //alert(response.data);

                    //Then on the button in the iFrame, call this on client click: 
                    if (typeof window.parent.parent.dialogClose == 'function') {
                        window.parent.parent.dialogClose();
                    }

                    if (callbackSuccess != undefined) {
                        callbackSuccess(response.data);
                    }

                }, function errorCallback(response) {
                    // called asynchronously if an error occurs
                    // or server returns response with an error status.
                    if (response.status != 200) {
                        if (response.data != '') {
                            if (callbackError != undefined) {
                                callbackError(response.data);
                            } else {
                                alert(response.data);
                            }
                        } else {
                            if (callbackError != undefined) {
                                callbackError(response.statusText);
                            } else {
                                alert(response.statusText);
                            }
                        }
                    }
                });
            }

            // reset model...
            vm.model = {};
            $scope.formData = {};
            $scope.vm.form.$setUntouched();
        }
    });
};


    function destroyApp(app) {
        /*
         * Iterate through the child scopes and kill 'em
         * all, because Angular 1.2 won't let us $destroy()
         * the $rootScope
         */
        var $rootScope = app.get('$rootScope');
        var scope = $rootScope.$$childHead;
        while (scope) {
            var nextScope = scope.$$nextSibling;
            scope.$destroy();
            scope = nextScope;
        }

        /*
         * Iterate the properties of the $rootScope and delete 
         * any that possibly were set by us but leave the 
         * Angular-internal properties and functions intact so we 
         * can re-use the application.
         */
        for (var prop in $rootScope) {
            if (($rootScope[prop])
                && (prop.indexOf('$$') != 0)
                && (typeof ($rootScope[prop]) === 'object')
                ) {
                $rootScope[prop] = null;
            }
        }
    }